// Generics 是指在定义函数、接口或类的时候，
// 不预先指定具体的类型，而在使用的时候再指定类型的一种特性。

// 不用泛型的话，这个函数可能是下面这样：
function identity(arg: number): number {
  return arg;
}

// 我们给identity添加了类型变量 T,T 帮助我们捕获用户传入的类型（比如： number ），
// 之后我们就可以使用这个类型。 之后我们再次使用了 T 当做返回值类型。
// 现在我们可以知道参数类型与返回值类型是相同的了。

// 泛型函数
function identity1<T>(arg: T) {
  return arg;
}
let output = identity1<string>('myString');
let output1: <T>(arg: T) => T = identity1;
// 泛型类型

// 泛型接口
interface GenericInterface {
  <T>(arg: T): T;
}
function genericFunc<T>(arg: T): T {
  return arg;
}
let myGenericFunc: GenericInterface = genericFunc;

interface GenericInterface2<T> {
  (arg: T): T;
}
function genericFunc2<T>(arg: T): T {
  return arg;
}
let myIdentity: GenericInterface2<number> = genericFunc2;

// 泛型类
// 泛型类看上去与泛型接口差不多。 泛型类使用（ <> ）括起泛型类型，跟在类名后面。
class GenericClass<T, Y> {
  aa: T;
  aaFuc: (arg: Y) => Y;
  zeroValue: T;
  add: (x: T, y: T) => T;
}

let myGenericClass = new GenericClass<number, string>();
myGenericClass.aa = 0;
myGenericClass.aaFuc = function(arg) {
  return arg;
};

let stringNumeric = new GenericClass<string, string>();
stringNumeric.zeroValue = '';
stringNumeric.add = function(x, y) {
  return x + y;
};
